from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", "window-type none")
loadPrcFileData("", "client-sleep 0.001")

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import *
from direct.task import Task
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.PyDatagramIterator import PyDatagramIterator
import sys

class Team():
    def __init__(self):
        self.playerlist = []
        self.alivelist = []
        self.score = 0
        self.maxteamplayers = 0
        self.teamchat = ""
        
class Client():
    def __init__(self):
        self.TimeOutCounter = 0
        self.target = NetAddress()
        self.id = ""
        self.damage = 0
        self.connection = 0
        self.name = "Default"
        self.X = 0
        self.Y = 0
        self.Z = 0
        self.H = 0
        self.P = 0
        self.R = 0
        self.HitPoints = 100
        self.alive = True
        self.ping = 0
        self.team = 0

    def CheckPlayer(self):
        if self.damage > 0:
            self.HitPoints -= self.damage
            self.damage = 0
        if self.HitPoints <= 0:
            self.alive = False
#Standard Packet - Position,Rotation - 0
#Gear Packet - Equiped,Armour,Hp - 1
#Chat Packet - Message,Mode - 2
import socket

class Server(DirectObject):
    def __init__(self):
        self.initNetwork()
        self.currentTime = 0
        #svar
        self.timeout = 10
        self.gravity = 9.81
        self.roundtime = 120
        self.oldroundtime = 0
        self.freezetime = 10
        self.buytime = 30
        self.winner = 0
        self.defaultwinner = 0
        self.terroists = Team()
        self.counterTerroists = Team()
    def initNetwork(self):
        print "Server Ip: " +str(socket.gethostbyname(socket.gethostname()))+ " Port: 35167"
        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.extrabuffer = ""
        self.clientList = {}
        self.target = NetAddress()
        self.target.setHost('127.0.0.1',35168)
        self.cWriter = ConnectionWriter(self.cManager,0)
        self.startServer()
    def NewRound(self):
          print "NEWROUND"
          for conec in self.clientList.keys():
            con = self.clientList[conec]
            if con.alive == False:
                con.alive = True
                con.HitPoints = 100
                if con.team == 0:
                    self.counterTerroists.alivelist.append(con.id)
                else:
                    self.terroists.alivelist.append(con.id)
          if self.winner == 0:
              self.writeTask("NewRound","Terrorist")
#                #do t win stuff here
          else:
              self.writeTask("NewRound","Counter")
#                #do ct win stuff
    def CheckTeams(self,task):
        self.remainTime = self.roundtime - (self.currentTime - self.oldroundtime)
        if len(self.clientList) > 1:
            if len(self.terroists.playerlist) <= 0:
                self.winner = 0
                self.oldroundtime = self.currentTime
                self.NewRound()
                return Task.cont
            if len(self.counterTerroists.playerlist) <= 0:
                self.winner = 1
                self.oldroundtime = self.currentTime
                self.NewRound()
                return Task.cont
        if self.oldroundtime <= self.currentTime - self.roundtime:
            self.winner = self.defaultwinner
            self.oldroundtime = self.currentTime
            self.NewRound()
            return Task.cont
        for conec in self.clientList.keys():
            con = self.clientList[conec]
            con.CheckPlayer()
            if con.alive == False:
                if con.team == 0:
                    self.counterTerroists.alivelist.remove(con.id)
                else:
                    self.terroists.alivelist.remove(con.id)
        return Task.cont

    def TimeOut(self,task):
        self.currentTime = globalClock.getFrameTime()
        for conec in self.clientList.keys():
            con = self.clientList[conec]
            if con.TimeOutCounter < self.currentTime - self.timeout:
                    print "Player " + con.name + " disconnected."
                    self.writeTask("Disconnected",con.id)
                    del self.clientList[con.id]
                    print "Players: " + str(len(self.clientList))
        return Task.cont


    def startServer(self):
        self.udpSocket = self.cManager.openUDPConnection(35167)
        if not self.udpSocket:
            print "WARNING: cannot Create UDP socket connection"
        self.cReader.addConnection(self.udpSocket)
        print 'Number of threads: ', self.cListener.getNumThreads()
        taskMgr.doMethodLater(0.2,self.readTask, "Read")
        taskMgr.doMethodLater(0.2,self.writeTask, "Write")
        taskMgr.doMethodLater(1,self.TimeOut, "playerchecks")
        taskMgr.doMethodLater(0.2,self.CheckTeams, "playerchecks")
        print "Server started"

    def HitWrite(self,task,who):
        if task == "HIT":
            p = self.clientList[who]
            package = PyDatagram()
            package.addUint8(len(self.clientList)-1)
            package.addString("HIT")
            package.addUint8(1)
            package.addFloat32(p.damage)
            self.cWriter.send(package,self.udpSocket,p.target)
        elif task == "Connect":
            p = self.clientList[who]
            package = PyDatagram()
            package.addUint8(len(self.clientList)-1)
            package.addString("CONNECT")
            package.addUint8(10)
            package.addFloat32(self.currentTime)
            self.cWriter.send(package,self.udpSocket,p.target)

    def writeTask(self,task,who = 0):
        for conec in self.clientList:
            con = self.clientList[conec]
            package = PyDatagram()
            package.addUint8(len(self.clientList)-1)
            CTteamlength = len(self.counterTerroists.playerlist)
            Tteamlength = len(self.counterTerroists.playerlist)
            for conni in self.clientList:
                conn = self.clientList[conni]
                if task == "NewRound":
                        package.addString("NEW")
                        package.addUint8(3)
                        package.addString(who)
                        if conn.team == 0:
                            package.addUint8(CTteamlength)
                            CTteamlength -=1
                        else:
                            package.addUint8(Tteamlength)
                            Tteamlength -=1
                if con != conn:
                    if task == "Disconnected":
                        package.addString(who)
                        package.addUint8(4)
                    else:
                        package.addString(conn.id)
                        package.addUint8(0)
                        package.addUint16(conn.team)
                        package.addFloat32(conn.X)
                        package.addFloat32(conn.Y)
                        package.addFloat32(conn.Z)
                        package.addFloat32(conn.H)
                        package.addFloat32(conn.P)
                        package.addFloat32(conn.R)
                        package.addFloat32(conn.HitPoints)
                        package.addFloat32(self.remainTime)
                        package.addString(conn.name)
            self.cWriter.send(package,self.udpSocket,con.target)
        return Task.cont

    def readTask(self,task):
        if self.cReader.dataAvailable():
            datagram = NetDatagram()
            if self.cReader.getData(datagram):
                sender = datagram.getAddress()
                if str(sender) not in self.clientList:
                    self.clientList[str(sender)] = Client()
                    self.clientList[str(sender)].target.setHost(str(sender),35168)
                    print "Player from " + str(sender) + " Joined"
                    print "Players: " + str(len(self.clientList))
                    if len(self.clientList) < 2:
                        self.NewRound()
                self.clientList[str(sender)].TimeOutCounter = globalClock.getFrameTime()
                message = PyDatagramIterator(datagram)
                Code = message.getInt16()
                if Code == 0:
                    player = self.clientList[str(sender)]
                    player.team = message.getUint16()
                    player.X = message.getFloat32()
                    player.Y = message.getFloat32()
                    player.Z = message.getFloat32()
                    player.H = message.getFloat32()
                    player.P = message.getFloat32()
                    player.R = message.getFloat32()
                    player.HitPoints = message.getFloat32()
                    player.name = message.getString()
                    player.id = str(sender)
                    if player.id not in self.terroists.playerlist and player.id not in self.counterTerroists.playerlist:
                        if len(self.terroists.playerlist) - len(self.counterTerroists.playerlist) > 0:
                            player.team = 0
                        else:
                            player.team = 1
                        if player.team == 0:
                            self.counterTerroists.playerlist.append(str(sender))
                        else:
                            self.terroists.playerlist.append(str(sender))
                if Code == 1:
                    who = message.getString()
                    if who in self.clientList:
                        dmg = message.getInt16()
                        self.clientList[who].damage = dmg
                        self.HitWrite("HIT",who)
                if Code == 4:
                    self.writeTask("Disconnected",str(sender))
                    del self.clientList[str(sender)]
                    print "Player " + con.name + " disconnected."
                    print "Players: " + str(len(self.clientList))
                if Code == 10:
                    self.clientList[str(sender)].ping = message.getFloat32()
                    self.HitWrite("Connect",str(sender))
        return Task.cont



Test = Server()
run()